package race;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;

/**
 * This class represents a competition between a list of {@link Operation}
 * istances, which are considered indeed as contenders in this race. Each
 * contender is asked to execute its own operation, and it's evaluated according
 * to its processing delay. This class is also responsible of all the
 * preparations required to make the race work properly, like the initialization
 * of all the contenders, wich is realized by the generation of a list of
 * pseudorandom integers. The list size (that is the race's route length) can be
 * easily set by the user, otherwise its value is the default of ten
 * 
 * @author simone
 * @since 1.2
 * @version 1.4
 * @see Operation
 *
 */
public class ProcessingTimeRace {

	private ArrayList<Ranking> raceRank;
	private ArrayList<Operation> listOperation;
	private ArrayList<Integer> randomList;
	private int routeLenght;

	/**
	 * Create a new race, with a given list of contenders
	 * 
	 * @param listOperations
	 *            : a list of {@link Operation} istances that will be the race
	 *            contenders
	 * @param raceRouteLenght
	 *            : the size of the set of data on wich the contenders will
	 *            execute their own operations
	 */
	public ProcessingTimeRace(ArrayList<Operation> listOperations,
			int raceRouteLenght) {
		this.listOperation = listOperations;
		this.routeLenght = raceRouteLenght;
		this.generateRandomList();
		for (Operation operation : listOperations) {
			operation.initializeOperationData(randomList);
		}
	}

	/**
	 * Returns the ranking list (sorted) of this race, wich means a list of
	 * processing time delays with the name of their relative contender
	 * 
	 * @return: raceRank
	 */
	public ArrayList<Ranking> getRaceRank() {
		this.startRace();
		Collections.sort(raceRank);
		return raceRank;
	}

	/**
	 * Let the race start
	 */
	public void startRace() {
		this.raceRank = new ArrayList<Ranking>();
		for (Operation op : listOperation) {
			Ranking placement = new Ranking(op.toString(),
					getProcessingTime(op));
			raceRank.add(placement);
		}
	}

	private String getProcessingTime(Operation op) {
		long initialTime = System.nanoTime();
		op.operate();
		long finalTime = System.nanoTime();
		return "" + (finalTime - initialTime);
	}

	private void generateRandomList() {
		Random random = new Random();
		randomList = new ArrayList<Integer>();
		for (int i = 0; i < this.routeLenght; i++) {
			randomList.add(random.nextInt());
		}
	}

}
